<!--
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-04-10 10:38:29
 * @Description  : 文件上传panel
-->
<template>
  <n-upload
    :custom-request="customRequest2"
    list-type="image-card"
    :max="1"
    v-model:file-list="previewFileList"
    @preview="handlePreview"
  />
  <n-modal
    v-model:show="showModal"
    preset="card"
    style="width: 600px"
    title="图片预览"
  >
    <img :src="previewImageUrl" style="width: 100%" />
  </n-modal>
</template>

<script setup lang="ts">
import MyWorker from '@/utils/worker.ts?worker'
import { fileChunkUpload, fileHandShark } from '@/api/file'
import type { IndexObj } from '@/types/commom'
import type { UploadTask } from '@/types/file'
import type { UploadFileInfo, UploadCustomRequestOptions } from 'naive-ui'

import { events } from '@/utils/bus'
import { BASE_URL } from '@/constants'

// const previewFileList = ref<UploadFileInfo[]>([])

const previewFileList = ref<any>([])
// 上传进度的task列表
const uploadList = ref<UploadTask[]>([])

watch(
  () => uploadList.value,
  () => {
    previewFileList.value = uploadList.value.map((item) => {
      return {
        id: item.id,
        url: item.url ? BASE_URL + item.url : '',
        name: item.filename,
        percentage: +item.percent,
        status: item.status
      }
    })

    console.log(previewFileList.value, 'xxx22')
  },
  {
    deep: true
  }
)

const showModal = ref(false)
const previewImageUrl = ref('')

const handlePreview = (file: UploadFileInfo) => {
  const { url } = file
  previewImageUrl.value = url as string
  showModal.value = true
}

const props = withDefaults(
  defineProps<{
    fileList: any[]
    parentId?: string
  }>(),
  {
    parentId: '-1'
  }
)

const emits = defineEmits<{
  (e: 'close'): void
  (e: 'fileChange', fileList: any): void
}>()

onBeforeMount(() => {
  events.off('upload-file')
})

onMounted(() => {
  events.on('upload-file', (res: any) => {
    uploadFiles(res.files)
  })
})

// 整体开始暂停开关
const fullStart = ref(false)

const handleFullTask = () => {
  fullStart.value = !fullStart.value
  if (!fullStart.value) {
    // 全部暂停
    uploadList.value.forEach((item) => {
      item.isPause = true
    })
  } else {
    // 全部开始
    uploadList.value.forEach((item) => {
      item.isPause = false
    })
  }
}

onMounted(() => {
  uploadList.value = props.fileList
  console.log(uploadList.value, props.fileList, 'xxx')
})

onUnmounted(() => {
  // explorerStore.setUploadTaskList(uploadList.value)
})

// 清空所有任务
const handleCleanAll = () => {
  uploadList.value = []
}

// 清空已完成任务
const handleCleanSuc = () => {
  uploadList.value = uploadList.value.filter((item) => {
    return +item.percent !== 100
  })
}

// 处理单个任务的暂停，开始
const handleSingerPause = (item: IndexObj) => {
  item.isPause = !item.isPause
  if (!item.isPause) {
    // 继续分片上传
    fileHandShark({
      fileId: item.fileId,
      filename: item.filename,
      size: '' + item.size,
      chunkIds: item.fileInfo.chunks.map((it: any) => it.id),
      parentId: item.parentId
    })
      .then((res) => {
        const needs = res.data.needs
        // if (!needs.length) {
        //   // uploadList.value.find((v) => v.id === item.id).percent = '100'
        //   item.percent = '100'
        // }
        // 说明需要继续上传
        uploadPiece(needs, item, res)
      })
      .catch((e) => {
        item.isPause = true
        console.error(e)
      })
  }
}

// 取消单个任务
const handleCancelUpload = (item: IndexObj) => {
  item.isPause = true
  // 从task中删除
  uploadList.value = uploadList.value.filter((v) => {
    return v.id !== item.id
  })
}

const fileInput = ref()
const handleSelectFile = () => {
  const input = fileInput.value
  if (input) {
    input.click()
  }
}
//  点击上传
const handleFileChange = (event: any) => {
  // console.log(event.target!.files)
  uploadFiles(event.target.files)
}

// 自定义上次
const customRequest = ({
  file,
  data,
  headers,
  withCredentials,
  action,
  onFinish,
  onError,
  onProgress
}: UploadCustomRequestOptions) => {
  // const formData = new FormData()
  // if (data) {
  //   Object.keys(data).forEach((key) => {
  //     formData.append(
  //       key,
  //       data[key as keyof UploadCustomRequestOptions['data']]
  //     )
  //   })
  // }
  // formData.append(file.name, file.file as File)

  console.log('aaa', 'ttt')

  console.log(file, data)
  uploadFiles([file.file])
}

const customRequest2 = ({
  file,
  data,
  headers,
  withCredentials,
  action,
  onFinish,
  onError,
  onProgress
}: UploadCustomRequestOptions) => {
  // const formData = new FormData()
  // if (data) {
  //   Object.keys(data).forEach((key) => {
  //     formData.append(
  //       key,
  //       data[key as keyof UploadCustomRequestOptions['data']]
  //     )
  //   })
  // }
  // formData.append(file.name, file.file as File)

  console.log('aaa', 'ttt')

  console.log(file, data)
  uploadFiles([file.file])
}

// 拖拽上传
const fileDragover = (e: DragEvent) => {
  console.log(e)
  e.preventDefault()
}

const fileDrop = (e: DragEvent) => {
  e.preventDefault()
  if (!e.dataTransfer) {
    return
  }
  const files = e.dataTransfer.files // 获取到所有的文件对象
  uploadFiles(files)
}

const uploadFiles = async (files: any) => {
  for (let i = 0; i < files.length; i++) {
    const random = Math.random().toString(16)
    const fileTask2: UploadTask = {
      id: 'xxx' + random,
      fileId: 'xxx' + random,
      parentId: '-1',
      filename: '文件计算中...',
      percent: 0,
      size: '0',
      type: 1,
      isPause: false,
      random,
      url: '',
      status: 'uploading',
      fileInfo: {
        fileId: 'xxx' + random,
        size: '0',
        filename: 'xxx' + random,
        chunks: []
      },
      needs: []
    }
    uploadList.value.push(fileTask2)
    const myWorker = new MyWorker()
    myWorker.postMessage({ file: files[i] })
    myWorker.onmessage = (e) => {
      handleCutSuccess(e.data)
      myWorker.terminate()
    }

    const handleCutSuccess = (fileInfo: any) => {
      uploadList.value = uploadList.value.filter(
        (item) => item.random !== random
      )
      fileInfo.random = random
      const fileTask: UploadTask = {
        id: fileInfo.fileId + random,
        fileId: fileInfo.fileId,
        parentId: '-1',
        filename: fileInfo.filename,
        percent: 0,
        size: fileInfo.size,
        type: 1,
        isPause: false,
        random,
        fileInfo,
        url: '',
        status: 'uploading',
        needs: []
      }
      uploadList.value.push(fileTask)
      fileHandShark({
        fileId: fileInfo.fileId,
        filename: fileInfo.filename,
        size: '' + fileInfo.size,
        chunkIds: fileInfo.chunks.map((it: any) => it.id),
        parentId: props.parentId
      })
        .then((res) => {
          const needs = res.data.needs
          // if (!needs.length) {
          //   fileTask.percent = '100'
          // return
          // }
          // 说明需要继续上传
          uploadPiece(needs, fileTask, res)
        })
        .catch((e) => {
          // 文件协商失败
          fileTask.isPause = true
          console.error(e)
        })
    }
  }
}

// 上传分片
const uploadPiece = async (needs: string[], fileTask: any, res: any) => {
  fileTask.needs = needs
  if (fileTask.isPause) {
    // 记录当前分片
    return
  }

  const curTask = uploadList.value.find((item) => item.id === fileTask.id)

  if (!curTask) {
    return
  }

  if (!needs || needs.length === 0) {
    curTask.percent = '100'
    // 部分图片已经上传成功
    curTask.url = res.data.url
    curTask.status = 'finished'
    // console.log(curTask, '666', uploadList.value)
    emits(
      'fileChange',
      uploadList.value.filter((item) => +item.percent === 100)
    )
    const isUpload = uploadList.value.every((item) => +item.percent === 100)
    if (isUpload) {
      emits('close')
    }
    return
  }
  const nextChunkId = needs[0]
  const file = fileTask.fileInfo.chunks.find(
    (it: any) => it.id === nextChunkId
  ).content
  const formData = new FormData()
  formData.append('file', file)
  formData.append('chunkId', nextChunkId)
  formData.append('fileId', fileTask.fileInfo.fileId)

  // 上传分片可能失败,这里可以限制上传次数
  let isSucCnt = 0
  while (isSucCnt < 5) {
    await fileChunkUpload(formData)
      .then((res) => {
        isSucCnt = 10
        needs = res.data.needs
        const allLength = fileTask.fileInfo.chunks.length
        curTask!.percent =
          Math.floor(((allLength - needs.length) / allLength) * 100) + ''
        uploadPiece(needs, fileTask, res)
      })
      .catch(() => {
        isSucCnt++
        // uploadPiece(needs, fileTask)
        console.log('error')
      })
  }

  if (isSucCnt === 5) {
    // 说明该分片上传失败，可以暂停该上传，提示上传失败
    fileTask.isPause = true
    console.error(fileTask.filename + '分片上传失败')
  }
}
</script>

<style scoped lang="scss">
.upload-panel {
  .upload-list {
    .item {
      display: flex;
      align-items: center;
      height: 35px;
      min-height: 35px;
      background: #fafdff;
      position: relative;
      margin-bottom: 5px;

      .close-icon {
        font-size: 22px;
        color: #ccc;
        &:hover {
          color: #ff4d4f;
        }
      }

      .inner-pro {
        left: 0;
        top: 0;
        bottom: 0;
        right: 0;
        position: absolute;
      }
    }
  }
}
</style>
